package com.sky.loveshop.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sky.loveshop.api.MeiTuanOrderRequest;
import com.sky.loveshop.entity.*;
import com.sky.loveshop.entity.aliPay.OrderDetailRequest;
import com.sky.loveshop.entity.exception.BizException;
import com.sky.loveshop.entity.exception.BizExceptionEnum;
import com.sky.loveshop.entity.meiTuan.MtOrderCreateResponse;
import com.sky.loveshop.entity.qo.PrivateOrderInfoQO;
import com.sky.loveshop.entity.vo.PrivateOrderInfoDetailVO;
import com.sky.loveshop.entity.vo.PrivateOrderInfoVO;
import com.sky.loveshop.entity.vo.SkuVO;
import com.sky.loveshop.entity.vo.UserVO;
import com.sky.loveshop.mapper.PrivateOrderInfoDetailMapper;
import com.sky.loveshop.mapper.PrivateOrderInfoMapper;
import com.sky.loveshop.service.*;
import com.sky.loveshop.utils.OrderUtils;
import com.sky.loveshop.utils.RedisUtil;
import com.sky.loveshop.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author xcy
 * @version V1.0
 * @description
 * @date 2024/12/25 22:32
 */
@Slf4j
@Service
public class PrivateOrderInfoServiceImpl implements PrivateOrderInfoService {

    @Autowired
    private PrivateOrderInfoMapper privateOrderInfoMapper;
    @Autowired
    private PrivateOrderInfoDetailMapper privateOrderInfoDetailMapper;
    @Autowired
    private SkuService skuService;
    @Autowired
    private ShopService shopService;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ProductService productService;
    @Autowired
    private MtService mtService;

    @Override
    public void addPrivateOrder(PrivateOrderInfoQO qo) throws BizException {

        // 先校验一下用户的积分是否大于0，且大于订单金额，积分不够的话不执行下面的逻辑
        UserVO user = userService.getUserById(qo.getUserId());
        if (user.getPoints() == null) {
            log.info("youHaveNotEnoughPoint userId:{}, points:{}", qo.getUserId(), user.getPoints());
            throw new BizException(BizExceptionEnum.YOU_HAVE_NOT_ENOUGH_POINT);
        }

        List<SkuVO> skuVOS = assembleOtherFields(qo.getOrderDetailRequestList(), qo);

        if (user.getPoints().compareTo(qo.getTotalAmount()) < 0) {
            log.info("youHaveNotEnoughPoint userId:{}, points:{}, totalAmount:{}", qo.getUserId(), user.getPoints(), qo.getTotalAmount());
            throw new BizException(BizExceptionEnum.YOU_HAVE_NOT_ENOUGH_POINT);
        }

        Map<Integer, SkuVO> id2InfoMap = skuVOS.stream().collect(Collectors.toMap(Sku::getId, Function.identity()));
        PrivateOrderInfo info = new PrivateOrderInfo();
        BeanUtils.copyProperties(qo, info);
        info.setOrderNo(OrderUtils.generatePrivateOrderNumber());
        // 新增主订单信息
        privateOrderInfoMapper.insert(info);

        // 新增订单详情信息
        List<PrivateOrderInfoDetail> detailList = new ArrayList<>();
        for (OrderDetailRequest d : qo.getOrderDetailRequestList()) {
            PrivateOrderInfoDetail detail = new PrivateOrderInfoDetail();
            detail.setOrderId(info.getId());
            detail.setOrderNo(info.getOrderNo());
            detail.setSkuId(d.getSkuId());
            detail.setProductId(id2InfoMap.get(d.getSkuId()).getProductId());
            detail.setProductName(id2InfoMap.get(d.getSkuId()).getProductName());
            detail.setNum(d.getNumber());
            detail.setPrice(id2InfoMap.get(d.getSkuId()).getBuyPrice());
            detail.setShelfId(id2InfoMap.get(d.getSkuId()).getShelfId());
            detail.setShelfNo(id2InfoMap.get(d.getSkuId()).getShelfName());
            detail.setShopId(id2InfoMap.get(d.getSkuId()).getShopId());
            detail.setShopName(id2InfoMap.get(d.getSkuId()).getShopName());
            detail.setBarCode(id2InfoMap.get(d.getSkuId()).getBarCode());
            detail.setCreateTime(new Date());
            detail.setUpc(id2InfoMap.get(d.getSkuId()).getUpc());
            detailList.add(detail);
        }
        addPrivateOrderDetails(detailList);

        // 扣减用户的积分
        Integer affectNum = userService.deducePoints(info.getUserId(), info.getTotalAmount());
        if (affectNum == 1) {
            info.setOrderStatus(1);

            // 调用外送帮接口进行下单配送
            MeiTuanOrderRequest.CreateOrderRequest createOrderRequest = new MeiTuanOrderRequest.CreateOrderRequest();
            createOrderRequest.setStore_id(info.getStoreId());
            createOrderRequest.setReceiver_name(info.getReceiverName());
            createOrderRequest.setReceiver_address(info.getReceiverAddress());
            createOrderRequest.setReceiver_phone(info.getReceiverPhone());
            createOrderRequest.setReceiver_lng(info.getReceiverLng());
            createOrderRequest.setReceiver_lat(info.getReceiverLat());
            createOrderRequest.setPlatform_order_id(info.getOrderNo());
            createOrderRequest.setPlatform_day_id(info.getPlatformDayId());
            createOrderRequest.setOrder_weight(info.getOrderWeight().intValue());
            createOrderRequest.setOrder_amount(info.getTotalAmount().toString());
            createOrderRequest.setRemark(info.getRemark());
            MtOrderCreateResponse response = mtService.createMtOrder(createOrderRequest);
            if (null == response || !response.isSuccess()) {
                // 积分已经扣减，订单显示下单成功，但是下单配送失败，这种情况需要人工介入处理，可能原因：收货人手机号不对，地址不对，街顺接口返回失败等
                log.error("createMtOrder failed 下单配送失败, 订单编号:{},  response:{}", info.getOrderNo(), response);
            }
        } else {
            info.setOrderStatus(2);
        }
        privateOrderInfoMapper.updateByPrimaryKey(info);
    }

    @Override
    public void addPrivateOrderDetails(List<PrivateOrderInfoDetail> detailList) {
        privateOrderInfoDetailMapper.insertList(detailList);
    }

    @Override
    public PageInfo<PrivateOrderInfoVO> listPrivateOrderInfoPages(PrivateOrderInfoQO qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        List<PrivateOrderInfoVO> orderInfoVOS = privateOrderInfoMapper.searchAll(qo);
        List<Integer> shopIds = orderInfoVOS.stream().map(PrivateOrderInfoVO::getShopId).distinct().collect(Collectors.toList());
        Map<Integer, String> id2ShopNameMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(shopIds)) {
            List<Shop> shopsByIds = shopService.getShopsByIds(shopIds);
            id2ShopNameMap = shopsByIds.stream().collect(Collectors.toMap(Shop::getId, Shop::getName));
        }
        Map<Integer, String> finalId2ShopNameMap = id2ShopNameMap;
        orderInfoVOS.stream().forEach(s -> {
            s.setShopName(finalId2ShopNameMap.get(s.getShopId()));
        });
        return new PageInfo<>(orderInfoVOS);
    }

    @Override
    public PrivateOrderInfoVO getPrivateOrderInfoById(Integer id) {
        PrivateOrderInfoVO vo = new PrivateOrderInfoVO();
        PrivateOrderInfo orderInfo = privateOrderInfoMapper.selectByPrimaryKey(id);
        BeanUtils.copyProperties(orderInfo, vo);
        Shop shop = shopService.getShopById(orderInfo.getShopId());
        vo.setShopName(shop.getName());
        List<PrivateOrderInfoDetail> orderDetailList = getDetailListByOrderId(id);

        List<Integer> productIds = orderDetailList.stream().map(PrivateOrderInfoDetail::getProductId).collect(Collectors.toList());
        List<PrivateOrderInfoDetailVO> list = new ArrayList<>();
        List<Product> products = productService.getProductsByIds(productIds);
        Map<Integer, String> id2picMap = products.stream().collect(Collectors.toMap(Product::getId, Product::getPicture));
        for (PrivateOrderInfoDetail d : orderDetailList) {
            PrivateOrderInfoDetailVO detailVO = new PrivateOrderInfoDetailVO();
            BeanUtils.copyProperties(d, detailVO);
            detailVO.setPicture(id2picMap.get(d.getProductId()));
            list.add(detailVO);
        }
        vo.setDetailList(list);
        return vo;
    }

    /**
     * 根据主订单id查询订单详情
     */
    @Override
    public List<PrivateOrderInfoDetail> getPrivateOrderInfoDetailsByOrderNo(String orderNo) {
        Example example = new Example(PrivateOrderInfoDetail.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("orderNo", orderNo);
        List<PrivateOrderInfoDetail> OrderDetails = privateOrderInfoDetailMapper.selectByExample(example);
        return OrderDetails;
    }

    /**
     * 根据主订单id查询订单详情
     */
    private List<PrivateOrderInfoDetail> getDetailListByOrderId(Integer orderId) {
        Example example = new Example(PrivateOrderInfoDetail.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("orderId", orderId);
        List<PrivateOrderInfoDetail> OrderDetails = privateOrderInfoDetailMapper.selectByExample(example);
        return OrderDetails;
    }

    /**
     * 组装其他的字段信息 计算订单总金额,标题,经纬度处理
     *
     * @param orderDetailRequestList
     * @return
     */
    private List<SkuVO> assembleOtherFields(List<OrderDetailRequest> orderDetailRequestList, PrivateOrderInfoQO qo) {
        List<Integer> skuIds = orderDetailRequestList.stream().map(OrderDetailRequest::getSkuId).collect(Collectors.toList());
        List<SkuVO> skuList = skuService.getSkuListByIds(skuIds);
        Map<Integer, BigDecimal> id2priceMap = skuList.stream().collect(Collectors.toMap(Sku::getId, Sku::getBuyPrice));
        Map<Integer, String> id2NameMap = skuList.stream().collect(Collectors.toMap(Sku::getId, SkuVO::getProductName));
        BigDecimal allTotalMoney = BigDecimal.ZERO;
        String subjectName = "";
        for (OrderDetailRequest d : orderDetailRequestList) {
            BigDecimal buyPrice = id2priceMap.get(d.getSkuId());
            BigDecimal num = BigDecimal.valueOf(d.getNumber().longValue());
            BigDecimal totalMoney = buyPrice.multiply(num);
            allTotalMoney = allTotalMoney.add(totalMoney);

            String s = id2NameMap.get(d.getSkuId());
            subjectName += s + d.getNumber() + "个";
        }
        qo.setTotalAmount(allTotalMoney);
        // 私域订单订单标题长度最大位256,超长用...表示
        String truncatedString = (subjectName.length() > 256) ? subjectName.substring(0, 253) + "..." : subjectName;
        qo.setSubject(truncatedString);
        dealLatLng(qo);

        qo.setPlatformDayId(Integer.parseInt(redisUtil.generatePlatformDayId()));

        qo.setOrderStatus(0);
        qo.setQueryOrderTimes(0);
        qo.setCreateTime(new Date());
        qo.setOrderWeight(1.0f);

        return skuList;
    }

    private void dealLatLng(PrivateOrderInfoQO qo) {
        if (StringUtils.isEmpty(qo.getLatLngString())) {
            return;
        }
        String a = qo.getLatLngString().trim();
        // 使用 split 方法分割字符串
        String[] parts = a.split("  "); // 分割纬度和经度
        String latitude = parts[0].split(":")[1]; // 取出纬度部分
        String longitude = parts[1].split(":")[1]; // 取出经度部分

        // 转换为 Float（注意可能会抛出 NumberFormatException，需要处理）
        try {
            Float lat = Float.valueOf(latitude.trim());
            Float lon = Float.valueOf(longitude.trim());
            qo.setReceiverLat(lat);
            qo.setReceiverLng(lon);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        String a = "纬度:39.91179  经度:116.39811 ";
        // 使用 split 方法分割字符串
        String[] parts = a.split("  "); // 分割纬度和经度
        String latitude = parts[0].split(":")[1]; // 取出纬度部分
        String longitude = parts[1].split(":")[1]; // 取出经度部分

        // 转换为 Float（注意可能会抛出 NumberFormatException，需要处理）
        try {
            Float lat = Float.valueOf(latitude.trim());
            Float lon = Float.valueOf(longitude.trim());
            System.out.println(lat); // 输出: 39.91179
            System.out.println(lon); // 输出: 116.39811
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }
}
